// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SRC_STUB_H_
#define SRC_STUB_H_

#include <stdint.h>
#include <string>

namespace seven_summits {

// Sends queries to a server. Client must call Connect()
// before first use, and HangUp() when done.
// @typeparam Request type of requests (proto message)
// @typeparam Response type of response (proto message)
template <class Request, class Response>
class Stub {
 public:
  virtual ~Stub() {}
  // Creates stub and transfers ownership to caller. The TCP connection
  // stays open until HangUp() is called.
  static Stub* CreateFromTcpHostPort(const std::string& tcp_host,
                                     int tcp_port);

  // Resolves host and connects.
  // Returns true if succesful.
  virtual bool Connect() = 0;

  // Sends query to server and waits for the result.
  // Returns true if succesful.
  virtual bool Query(const Request& request, Response* response) = 0;

  // Says good-bye and disconnects from server.
  // Returns true if succesful.
  virtual bool HangUp() = 0;

 protected:
  Stub() {}
};

template <class Request, class Response>
class TcpHostPortStub : public Stub<Request, Response> {
 public:
  virtual ~TcpHostPortStub() {}

  // implementation of Stub methods

  virtual bool Connect();
  virtual bool Query(const Request& request, Response* response);
  virtual bool HangUp();

 private:
  friend Stub<Request, Response>*
      Stub<Request, Response>::CreateFromTcpHostPort(const std::string&, int);

  enum {
    kUndefined = -1,
    kBufSize = 1 << 12,
  };
  TcpHostPortStub(const std::string& tcp_host, int tcp_port)
      : tcp_host_(tcp_host),
        tcp_port_(tcp_port),
        sfd_(kUndefined)  {}

  const std::string tcp_host_;
  int tcp_port_;
  int sfd_;
};

}  // namespace seven_summits

#endif // SRC_STUB_H_
